/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: a1227
 * Date: 2022-07-25
 * Time: 11:12
 */
//双向链表的节点
class ListNode{
    public int val;//数据域
    public ListNode prev;//前驱
    public ListNode next;//后继
    //构造方法
    public ListNode(int val){
        this.val = val;
    }
}

public class MyLinkedList {
    public ListNode head;//头节点
    public ListNode tail;//尾节点

    //头插法
    public void addFirst(int data){
        //要头插的新节点
        ListNode newNode = new ListNode(data);
        //如果双向链表为空的情况
        if(this.head == null){
            this.head = this.tail = newNode;
            return ;
        }
        //双向链表不为空，有大于等于1个元素的情况
        newNode.next = this.head;
        this.head.prev = newNode;
        this.head = newNode;
    }

    //尾插法
    public void addLast(int data){
        //要尾插的新节点
        ListNode newNode = new ListNode(data);
        //如果双向链表为空的情况
        if(this.head == null){
            this.head = this.tail = newNode;
            return ;
        }
        //双向链表不为空，有大于等于1个元素的情况
        newNode.prev = this.tail;
        this.tail.next = newNode;
        this.tail = newNode;
    }

    //返回下标index所在位置的节点
    public ListNode searchIndex(int index){
        ListNode cur = this.head;
        //从头指针开始走index步，每走一步index--
        while(index-- != 0){
            cur = cur.next;
        }
        return cur;
    }

    //在任意位置前插入,ps：第一个数据节点为0号下标
    public void addIndex(int index,int data){
        //判断index位置是否合法
        if(index < 0 || index > size()){
            System.out.println("index位置不合法！");
            return ;
        }
        ListNode cur = searchIndex(index);//接收index位置的节点
        ListNode newNode = new ListNode(data);
        //当cur等于头节点，调用头插
        if(cur == this.head){
            addFirst(data);
            return ;
        }
        //当cur等于null，调用尾插
        if(cur == null){
            addLast(data);
            return ;
        }
        //其余情况
        cur.prev.next = newNode;
        newNode.next = cur;
        newNode.prev = cur.prev;
        cur.prev = newNode;
    }

    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = this.head;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    //删除第一次出现关键字为key的节点
    public void remove(int key){
        ListNode cur = this.head;
        while(cur != null){
            //cur的val为key的情况
            if(cur.val == key){
                //当要删除的val在头节点时
                if(cur == this.head){
                    //当双向链表只有一个元素时
                    if(cur == this.tail){
                        this.head = this.tail = null;
                        return ;
                    }
                    //当要删除的val在头节点时
                    this.head = this.head.next;
                    this.head.prev = null;
                    return;
                    //当要删除的val不在头节点时
                }else{
                    cur.prev.next = cur.next;
                    //当要删除的val在尾节点时
                    if(cur == this.tail){
                        this.tail = this.tail.prev;
                        return ;
                    }
                    //当要删除的val不在尾节点时
                    cur.next.prev = cur.prev;
                    return ;
                }
            }
            //cur的val不为key的情况
            cur = cur.next;
        }
    }

    //删除所有值为key的节点
    public void removeAllKey(int key){
        ListNode cur = this.head;
        while(cur != null){
            //cur的val为key的情况
            if(cur.val == key){
                //当要删除的val在头节点时
                if(cur == this.head){
                    //当双向链表只有一个元素时
                    if(cur == this.tail){
                        this.head = this.tail = null;
                        //当要删除的val在头节点且双向链表不知一个元素时
                    }else{
                        this.head = this.head.next;
                        this.head.prev = null;
                    }
                    //当要删除的val不在头节点时
                }else{
                    cur.prev.next = cur.next;
                    //当要删除的val在尾节点时
                    if(cur == this.tail){
                        this.tail = this.tail.prev;
                        //当要删除的val不在尾节点时
                    }else{
                        cur.next.prev = cur.prev;
                        return ;
                    }
                }
            }
            //cur的val不为key的情况
            cur = cur.next;
        }
    }

    //得到双向链表的长度
    public int size(){
        ListNode cur = this.head;
        int count = 0;//计数
        while(cur != null)
        {
            count++;
            cur = cur.next;
        }
        return count;
    }

    //打印双向链表
    public void display(){
        ListNode cur = this.head;
        while(cur != null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

    //清空双向链表
    public void clear(){
        //暴力清空法
        /*this.head = null;
        this.tail = null;*/
        //温柔清空法
        while(this.head != null){
            //存储head的next节点
            ListNode headNext = this.head.next;
            //一个接一个的清除节点
            this.head.prev = null;
            this.head.next = null;
            this.head = headNext;
        }
        //最后把尾节点也清除了
        this.tail = null;
    }
}
